<template>
  <form class="page page-mp4-meta-position">
    <h4 class="text-center">批量修改mp4的meta信息位置</h4>
    <div class="fieldset-options row">
      <div class="col-9">
        <fieldset>
          <legend>参数设置</legend>
          <div class="form-group row-flex" align="center">
            <div class="row-flex-prefix">保存位置</div>
            <div class="row-flex-main"><input class="form-control" type="text" v-model="toPath" /></div>
            <div class="row-flex-suffix"><x-button @click="setToPath">选择</x-button></div>
          </div>
          <div class="form-group row-flex" align="center">
            <div class="row-flex-prefix">META位置</div>
            <div class="row-flex-main radio-list">
              <label><input class="form-check-input" type="radio" value="before" v-model="metaPosition">放在头部</label>
              <label><input class="form-check-input" type="radio" value="after" v-model="metaPosition">放在尾部</label>
            </div>
          </div>
        </fieldset>
      </div>
      <div class="col-3">
        <fieldset class="flex-center">
          <legend>操作</legend>
          <div class="form-group">
            <x-button type="default" block @click="preview" :disabled="loadingCount > 0">信息预检</x-button>
          </div>
          <div class="form-group">
            <x-button type="primary" block @click="execute" :loading="loadingCount > 0">批量处理</x-button>
          </div>
        </fieldset>
      </div>
    </div>
    <fieldset class="fieldset-content">
      <legend>文件列表</legend>
      <div class="row-flex" align="center">
        <div class="row-flex-main text-left">共 {{filesList.length}} 个文件</div>
        <div class="row-flex-suffix">
          <button type="button" class="btn btn-link" @click="clearFilesList" title="清空">
            <i class="fa fa-trash-o"></i>
          </button>
        </div>
      </div>
      <div class="table-header" :style="thStyles">
        <table>
          <tbody>
            <tr>
              <th v-for="(v,i) in tableHeaders" :key="`th_${i}`" :style="{width: v.width}">{{v.label}}</th>
            </tr>
          </tbody>
        </table>
      </div>
      <div class="table-body" @drop.prevent="filesDrop" @dragover.prevent>
        <table ref="table">
          <tbody>
            <tr v-for="(v,i) in filesList" :key="`file_${i}`">
              <template v-for="(item,index) in tableHeaders">
                <td :style="{width: item.width}" :key="`td_${i}_${index}`">
                  <button v-if="item.value==='action'" type="button" class="btn btn-link" @click="deleteFileItem(i)" title="删除">
                    <i class="fa fa-close"></i>
                  </button>
                  <span v-else>{{v[item.value] || ''}}</span>
                </td>
              </template>
            </tr>
            <tr v-if="filesList.length===0" class="nodata-tr"><td>将待处理的文件拖动到此处</td></tr>
          </tbody>
        </table>
      </div>
      <div v-if="loadingCount > 0" class="mask">
        <x-loading></x-loading>
      </div>
    </fieldset>
  </form>
</template>

<script>
const fs = global.require('fs')
const path = global.require('path')
const {remote} = global.require('electron')
const {dialog} = remote
const selfWindow= remote.getCurrentWindow()
let {faststart} = global.moovFaststart || {}
let mp4MoovMove = global.mp4MoovMove || null

export default {
  name: 'mp4-meta-position',
  data () {
    return {
      filesList: [],
      tasksList: [],
      toPath: this.$sharedObject('desktopPath'),
      metaPosition: 'before',
      tableHeaders: [
        {label: '文件名', value: 'fileName', width: '30%'},
        {label: '当前META位置', value: 'position', width: '30%'},
        {label: '状态', value: 'status', width: '20%'},
        {label: '操作', value: 'action', width: '20%'},
      ],
      thStyles: {},
      loadingCount: 0
    }
  },
  computed: {
    filePathsList () {
      return this.filesList.map(v => v.path)
    }
  },
  mounted () {
    faststart = this.$sharedObject('moovFaststart').faststart
    mp4MoovMove = this.$sharedObject('mp4MoovMove')
  },
  methods: {
    // 设置保存位置
    setToPath () {
      let filePaths = dialog.showOpenDialogSync(selfWindow, {
        title: '选择目录',
        buttonLabel:'确定',
        defaultPath: this.$sharedObject('desktopPath'),
        properties: ['openDirectory']
      })
      if (filePaths instanceof Array && filePaths.length > 0) {
        this.toPath = filePaths[0]
      }
    },
    // 拖拽待处理文件
    filesDrop (e) {
      const filesList = e.dataTransfer.files
      if (!filesList) return
      for (let i = 0; i < filesList.length; i++) {
        const file = filesList[i]
        if (!this.filePathsList.includes(file.path)) {
          let fileName = path.basename(file.path) || file.name
          this.filesList.push({
            path: file.path,
            fileName,
            position: '',
            status: '',
            boxes: null
          })
        }
      }
      this.checkScroll()
    },
    // 删除条目
    deleteFileItem (index) {
      this.filesList.splice(index, 1)
      this.checkScroll()
    },
    // 清空待处理文件
    clearFilesList () {
      this.filesList = []
      this.tasksList = []
      this.thStyles = {}
      this.loadingCount = 0
    },
    checkScroll () {
      this.$nextTick(() => {
        if (!this.$refs.table) return
        let tableHeight = this.$refs.table.clientHeight
        let tableParentHeight = this.$refs.table.parentNode.clientHeight
        if (tableHeight > tableParentHeight) {
          this.thStyles = {overflow: 'hidden scroll'}
        } else {
          this.thStyles = {overflow: 'hidden'}
        }
      })
    },
    // 信息预检
    preview () {
        this.loadingCount++
        this.$nextTick(() => {
            let filesList = this.$jstools.deepCopy(this.filesList)
            this.filesList = filesList.map(v => {
                let file = fs.readFileSync(v.path, {encoding: null})
                let info = {boxes: null, p_mdat: -1, p_moov: -1}
                let position = ''
                let status = ''
                try {
                    info = mp4MoovMove.getPositionInfo(file)
                } catch (err) {
                  info.p_moov = file.indexOf('moov')
                  info.p_mdat = file.indexOf('mdat')
                }
                if (info.p_moov === -1) {status = '未找到moov'}
                else if (info.p_mdat === -1) {status = '未找到mdat'}
                else if (info.p_moov > info.p_mdat) {position = '文件尾部'}
                else if (info.p_moov < info.p_mdat) {position = '文件头部'}
                return {
                    ...v, boxes: info.boxes, position, status
                }
            })
            this.loadingCount--
        })
    },
    // 批量处理
    execute () {
        let _this = this
        let position = this.metaPosition === 'before' ? '文件头部' : '文件尾部'
        this.filesList.forEach((v, i) => {
            this.loadingCount++
            this.$set(this.filesList[i], 'status', '处理中')
            setTimeout(() => {
                let file = fs.readFileSync(v.path)
                let buf = null
                let p_moov = file.indexOf('moov')
                let p_mdat = file.indexOf('mdat')
                if (p_moov === -1 || p_mdat === -1
                  || (_this.metaPosition === 'before' && p_moov < p_mdat)
                  || (_this.metaPosition === 'after' && p_moov > p_mdat)
                ) {
                  buf = file
                } else {
                  try {
                      buf = mp4MoovMove[_this.metaPosition](file, v.boxes)
                  } catch (err) {
                      if (_this.metaPosition === 'before') {
                          try {
                              buf = faststart(file)
                          } catch (err) {
                              _this.$set(_this.filesList[i], 'status', '处理失败')
                              _this.loadingCount--
                          }

                      } else {
                          _this.$set(_this.filesList[i], 'status', '处理失败')
                          _this.loadingCount--
                      }
                  }
                }
                if (!buf) return
                let filePath = path.join(this.toPath, v.fileName)
                this.tasksList.push(
                    this.$sharedObject('jstoolsNode').writeFile(filePath, buf).then(() => {
                        this.$set(this.filesList[i], 'position', position)
                        this.$set(this.filesList[i], 'status', '已完成')
                    }).finally(() =>{
                        this.loadingCount--
                    })
                )
            }, 100)
        })
        Promise.all(this.tasksList).finally(() => {
            this.tasksList = []
            this.$toast('处理完成')
        })
    },
  }
}
</script>

<style scoped lang="less">
@import "~@/assets/css/_mixins.less";
@import "~@/assets/css/_color.less";
.page-mp4-meta-position {
	display: flex;
	flex-direction: column;
  .row-flex-prefix {
    text-align: left;
  }
  fieldset {
    margin-top: 1em;
    .row-flex-prefix {width: 5em;}
  }
	.fieldset-content {
		height: 0;
		flex-grow: 1;
        position: relative;
    .table-header,
    .table-body {
      table {
        width: 100%;
        border: 1px solid @borderGrey;
        tr {height: 2em;}
        th, td {
          border: 1px solid @borderGrey;
          text-align: center;
          vertical-align: middle;
        }
        .nodata-tr {
          height: 100%;
          font-size: 16px;
          color: #999;
        }
      }
    }
    .table-body {
      height: calc(100% - 6.5em);
      overflow: auto;
      table {
        min-height: 100%;
      }
    }
    .mask {
      position: absolute;
      left: 15px;
      right: 15px;
      top: 0;
      bottom: 0;
      border-radius: 8px;
      background-color: rgba(255,255,255,.5);
      .flex-center;
    }
  }
  .fieldset-options {
    fieldset {
      height: calc(100% - 1em);
    }
  }
  .radio-list {
    text-align: left;
    label {margin-right: 1.5em;}
  }
}
</style>
